﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Haro.Core
{
    public class Settings
    {
        public Debug.DebugType DebugOutputType = Debug.DebugType.Text;

        public bool DebugEnabled = false;
        public bool ListeningEnabled = true;

        public int SpeechOutputVolume = 100;

        public string[] ModulesToLoadAtStartup;

        public string[] DebugOn_Commands = { "Debug on.", "Turn on debugging." };
        public string[] DebugOff_Commands = { "Debug off." };
        public string[] ListModules_Commands = { "List modules." };
        public string[] ScanForModules_Commands = { "Scan for new modules." };
        public string[] ScanAndLoadAll_Commands = { "Scan and add all modules." };
        public string[] Mute_Commands = { "Mute." };
        public string[] Unmute_Commands = { "Unmute." };
        public string[] Goodbye_Commands = { "Goodbye." };
        public string[] LoadModule_Commands = { "Load module    " };
        public string[] UnloadModule_Commands = { "Unload module  " };

        #region Constructors
        public Settings()
        {
        }

        public Settings(string[] Modules)
        {
            ModulesToLoadAtStartup = Modules;
            ApplySettings();
        }
        #endregion

        #region ApplySettings
        /// <summary>
        /// Applies the settings as specified within its variables for Haro such
        /// as the commands, debug states, etc.
        /// </summary>
        public void ApplySettings()
        {
            Haro.Debug.OutputType = DebugOutputType;
            Haro.Debug.Enabled = DebugEnabled;

            Speech.SpeechOutput.Volume = SpeechOutputVolume;

            Globals.Commands.Clear();

            foreach (string s in DebugOn_Commands)
                Globals.Commands.Add(s, Globals.CommandType.DebugOn);
            foreach (string s in DebugOff_Commands)
                Globals.Commands.Add(s, Globals.CommandType.DebugOff);
            foreach (string s in ListModules_Commands)
                Globals.Commands.Add(s, Globals.CommandType.ListModules);
            foreach (string s in ScanForModules_Commands)
                Globals.Commands.Add(s, Globals.CommandType.ScanForModules);
            foreach (string s in ScanAndLoadAll_Commands)
                Globals.Commands.Add(s, Globals.CommandType.ScanAndLoadAllModules);
            foreach (string s in Mute_Commands)
                Globals.Commands.Add(s, Globals.CommandType.Mute);
            foreach (string s in Unmute_Commands)
                Globals.Commands.Add(s, Globals.CommandType.Unmute);
            foreach (string s in Goodbye_Commands)
                Globals.Commands.Add(s, Globals.CommandType.Goodbye);
            foreach (string s in LoadModule_Commands)
                Globals.Commands.Add(s, Globals.CommandType.LoadModule);
            foreach (string s in UnloadModule_Commands)
                Globals.Commands.Add(s, Globals.CommandType.UnloadModule);
        }
        #endregion

        #region GatherSettings
        /// <summary>
        /// Gathers the settings and stores them with its variables.
        /// </summary>
        public void GatherSettings()
        {
            // Accquires the first two and easily fetched settings.
            DebugOutputType = Haro.Debug.OutputType;
            DebugEnabled = Haro.Debug.Enabled;

            SpeechOutputVolume = Speech.SpeechOutput.Volume;

            // Creates counters for the lenghts of the arrays of commands.
            int _debugOff = 0, _debugOn = 0, _goodbye = 0, _listModules = 0, _loadModule = 0, _mute = 0,
                _scanAndLoadAllModules = 0, _scanForModules = 0, _unloadModule = 0, _unmute = 0;

            // Measures the required length for each array.
            foreach (KeyValuePair<string, Globals.CommandType> kvp in Globals.Commands)
            {
                switch (kvp.Value)
                {
                    case Globals.CommandType.DebugOff:
                        _debugOff++;
                        break;
                    case Globals.CommandType.DebugOn:
                        _debugOn++;
                        break;
                    case Globals.CommandType.Goodbye:
                        _goodbye++;
                        break;
                    case Globals.CommandType.ListModules:
                        _listModules++;
                        break;
                    case Globals.CommandType.LoadModule:
                        _loadModule++;
                        break;
                    case Globals.CommandType.Mute:
                        _mute++;
                        break;
                    case Globals.CommandType.ScanAndLoadAllModules:
                        _scanAndLoadAllModules++;
                        break;
                    case Globals.CommandType.ScanForModules:
                        _scanForModules++;
                        break;
                    case Globals.CommandType.UnloadModule:
                        _unloadModule++;
                        break;
                    case Globals.CommandType.Unmute:
                        _unmute++;
                        break;
                    default: break;
                }
            }

            // Initializes all the arrays to their required lengths.
            DebugOff_Commands = new string[_debugOff];
            DebugOn_Commands = new string[_debugOn];
            Goodbye_Commands = new string[_goodbye];
            ListModules_Commands = new string[_listModules];
            LoadModule_Commands = new string[_loadModule];
            Mute_Commands = new string[_mute];
            ScanAndLoadAll_Commands = new string[_scanAndLoadAllModules];
            ScanForModules_Commands = new string[_scanForModules];
            UnloadModule_Commands = new string[_unloadModule];
            Unmute_Commands = new string[_unmute];

            // Resets all the counters to 0 so that they can be used as array indicies.
            _debugOff = _debugOn = _goodbye = _listModules = _loadModule = _mute =
                _scanAndLoadAllModules = _scanForModules = _unloadModule = _unmute = 0;

            // The following code inserts the commands into the respective command lists.
            foreach (KeyValuePair<string, Globals.CommandType> kvp in Globals.Commands)
            {
                switch(kvp.Value)
                {
                    case Globals.CommandType.DebugOff:
                        DebugOff_Commands[_debugOff++] = kvp.Key;
                        break;
                    case Globals.CommandType.DebugOn:
                        DebugOn_Commands[_debugOn++] = kvp.Key;
                        break;
                    case Globals.CommandType.Goodbye:
                        Goodbye_Commands[_goodbye++] = kvp.Key;
                        break;
                    case Globals.CommandType.ListModules:
                        ListModules_Commands[_listModules++] = kvp.Key;
                        break;
                    case Globals.CommandType.LoadModule:
                        LoadModule_Commands[_loadModule++] = kvp.Key;
                        break;
                    case Globals.CommandType.Mute:
                        Mute_Commands[_mute++] = kvp.Key;
                        break;
                    case Globals.CommandType.ScanAndLoadAllModules:
                        ScanAndLoadAll_Commands[_scanAndLoadAllModules++] = kvp.Key;
                        break;
                    case Globals.CommandType.ScanForModules:
                        ScanForModules_Commands[_scanForModules++] = kvp.Key;
                        break;
                    case Globals.CommandType.UnloadModule:
                        UnloadModule_Commands[_unloadModule++] = kvp.Key;
                        break;
                    case Globals.CommandType.Unmute:
                        Unmute_Commands[_unmute++] = kvp.Key;
                        break;
                    default: break;
                }
            }
        }
        #endregion

        #region AddStartupModule
        /// <summary>
        /// Adds the specified module to the list of startup modules.
        /// </summary>
        /// <param name="ModuleName">String containing the name of the module to be added.</param>
        public void AddStartupModule(string ModuleName)
        {
            string[] list;
            if (ModulesToLoadAtStartup != null)
            {
                list = new string[ModulesToLoadAtStartup.Length + 1];

                for (int i = 0; i < ModulesToLoadAtStartup.Length; i++)
                    list[i] = ModulesToLoadAtStartup[i];

                list[ModulesToLoadAtStartup.Length] = ModuleName;
            }
            else
            {
                list = new string[1];
                list[0] = ModuleName;
            }

            ModulesToLoadAtStartup = list;

            foreach (string s in ModulesToLoadAtStartup)
                Debug.Output("Adding to startup: " + s);
        }
        #endregion

        #region RemoveStartupModule
        /// <summary>
        /// Removes the specified module frmo the startup module list.
        /// </summary>
        /// <param name="ModuleName">String containing the name of the module to be removed from the
        /// startup module list.</param>
        public void RemoveStartupModule(string ModuleName)
        {
            if (ModulesToLoadAtStartup != null)
            {
                int i = 0;
                string[] list = new string[ModulesToLoadAtStartup.Length - 1];

                foreach (string s in ModulesToLoadAtStartup)
                {
                    if (!s.Equals(ModuleName))
                        list[i++] = s;
                }

                ModulesToLoadAtStartup = list;
            }
        }
        #endregion
    }
}
